﻿@using Gurux.DLMS.AMI.Client.Pages.Admin
@using Gurux.DLMS.AMI.Client.Pages.Media;
@using Gurux.DLMS.AMI.Client.Pages.Script
@using Gurux.DLMS.AMI.Shared
@using Gurux.DLMS.Enums
@using Gurux.Net;
@using Gurux.Serial;
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using Gurux.DLMS.AMI.Shared.DTOs.Authentication
@using Gurux.DLMS.AMI.Shared.DTOs
@using Gurux.DLMS.AMI.Shared.Rest
@using Gurux.DLMS.AMI.Shared.Enums
@using Gurux.DLMS.AMI.Client.Helpers
@using Gurux.DLMS.AMI.Module
@using System.Diagnostics
@inject HttpClient Http
@if (Settings != null)
{
    <EditForm Model="@Settings">
        <DataAnnotationsValidator />
        <GXValidator @ref="_validator" OnValidate="OnValidate" />
        <div class="row">
            <div style="width:100%">
                <div class="form-group row">
                    <InputSwitch Text="@Properties.Resources.Active"
                    @bind-Value="Settings.Active" />
                    <br />
                </div>
                <fieldset disabled="@(!Settings.Active)">
                    @if (!IsSerialPort())
                    {
                        <NetworkSettings IsServer="true" @bind-Settings="@Settings.MediaSettings"
                        @ref=networkSettings></NetworkSettings>
                    }
                    else
                    {
                        <SerialSettings @bind-Settings="@Settings.MediaSettings"
                        @ref=serialSettings></SerialSettings>
                    }
                    <div class="form-group row">
                        <label style="margin:auto">Interface</label>
                        <select class="form-select" @bind="@Settings.Interface">
                            @foreach (var it in InterfaceList)
                            {
                                <option value="@Convert.ToInt32(it)">@it</option>
                            }
                        </select>
                    </div>
                    <div class="form-group row">
                        <InputCheckbox @bind-Value="Settings.UseLogicalNameReferencing" />
                        <label>@Properties.Resources.UseLogicalNameReferencing</label>
                        <br />
                    </div>
                    <div class="form-group row">
                        <label>@Properties.Resources.ExpirationTime</label>
                        <InputNumber id="threads" class="form-control"
                        @bind-Value="Settings.ExpirationTime" />
                        <ValidationMessage For="@(() => Settings.ExpirationTime)" />
                    </div>
                    <div class="form-group row">
                        <label>@Properties.Resources.Script</label>
                        <ScriptMethodSelector Scripts="@Scripts"
                                              SelectionChanged="@SelectionChanged"
                                              ScriptMethod="@Settings.ScriptMethod"></ScriptMethodSelector>
                    </div>
                    <div class="form-group row">
                        <div class="form-group">
                            <label>@Properties.Resources.DefaultDeviceTemplate</label>
                            <DropdownSearch Context="item"
                            @bind-Value="DefaultDeviceTemplate"
                                            ItemsProvider="@GetItems">
                                <ItemContent>
                                    @item.Name
                                </ItemContent>
                            </DropdownSearch>
                        </div>
                    </div>
                    <div class="form-group row">
                        <label>@Properties.Resources.TraceLevels</label>
                        <select class="form-select" @bind="Settings.TraceLevel">
                            @foreach (var it in TraceLevels)
                            {
                                <option value="@it"> @it </option>
                            }
                        </select>
                    </div>
                </fieldset>
            </div>
        </div>
    </EditForm>
}

@code {
    //Available scripts.
    [Parameter]
    public GXScript[]? Scripts { get; set; }

    [Parameter]
    public NotifySettings? Settings { get; set; }

    private GXValidator? _validator;

    InterfaceType[] InterfaceList = new InterfaceType[] {
        InterfaceType.HDLC,
        InterfaceType.WRAPPER,
        InterfaceType.WirelessMBus,
        InterfaceType.WiredMBus
    };

    Enums.Authentication[] Authentications = new Enums.Authentication[]
    {
        Enums.Authentication.None,
        Enums.Authentication.Low,
        Enums.Authentication.High,
        Enums.Authentication.HighGMAC
    };
    Enums.Security[] Securities = new Enums.Security[] {
        Enums.Security.None,
        Enums.Security.Encryption,
        Enums.Security.Authentication,
        Enums.Security.AuthenticationEncryption
    };

    TraceLevel[] TraceLevels = new TraceLevel[] {
        TraceLevel.Off,
        TraceLevel.Error,
        TraceLevel.Warning,
        TraceLevel.Info,
        TraceLevel.Verbose };

    private GXSerialTemplate _serial = new GXSerialTemplate();
    private Gurux.Net.GXNet _net = new Gurux.Net.GXNet();

    private string? _serialPort;

    GXDeviceTemplate _defaultDeviceTemplate = new GXDeviceTemplate(Properties.Resources.Nothing);
    private GXDeviceTemplate DefaultDeviceTemplate
    {
        get
        {
            return _defaultDeviceTemplate;
        }
        set
        {
            _defaultDeviceTemplate = value;
            if (Settings != null)
            {
                if (value.Id == Guid.Empty)
                {
                    Settings.DefaultDeviceTemplate = null;
                }
                else
                {
                    Settings.DefaultDeviceTemplate = value.Id;
                }
            }
        }
    }

    /// <summary>
    /// The serial port of the agent.
    /// </summary>
    [Parameter]
    public string? SerialPort
    {
        get => _serialPort;
        set
        {
            if (_serialPort != value)
            {
                _serialPort = value;
                SerialPortChanged.InvokeAsync(value);
            }
        }
    }

    /// <summary>
    /// Is serial port used.
    /// </summary>
    /// <returns></returns>
    private bool IsSerialPort()
    {
        return !string.IsNullOrEmpty(_serialPort);
    }

    /// <summary>
    /// Notified when settings are updated.
    /// </summary>
    [Parameter]
    public EventCallback<string?> SerialPortChanged { get; set; }


    NetworkSettings? networkSettings { get; set; }
    SerialSettings? serialSettings { get; set; }

    public void Validate(GXValidator sender)
    {
        OnValidate(sender);
        _validator?.Validate();
    }

    public void OnValidate(GXValidator sender)
    {
        @if (Settings != null && Settings.Active)
        {
            if (Settings.ExpirationTime < 0)
            {
                sender.AddError(() => Settings.ExpirationTime, "Invalid expiration time.");
            }
            if (Settings?.MediaType == typeof(GXNet).FullName)
            {
                networkSettings?.Validate(sender);
            }
            else if (Settings?.MediaType == typeof(GXSerial).FullName)
            {
                serialSettings?.Validate(sender);
            }
        }
    }

    ///<summary>
    ///Script method has been changed.
    ///</summary>
    private void SelectionChanged(Guid? guid)
    {
        if (Settings != null)
        {
            Settings.ScriptMethod = guid;
        }
    }

    protected override void OnInitialized()
    {
        if (string.IsNullOrEmpty(Settings?.MediaType) && Settings != null)
        {
            Settings.MediaType = typeof(GXNet).FullName;
        }
        if (Settings != null && Settings?.DefaultDeviceTemplate != null &&
           Settings?.DefaultDeviceTemplate.Value != Guid.Empty)
        {
            _defaultDeviceTemplate = new GXDeviceTemplate()
                {
                    Id = Settings.DefaultDeviceTemplate.Value,
                    Name = Properties.Resources.Nothing
                };
        }
    }

    /// <summary>
    /// Filter is done when SearchSelectedByName is called.
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    private async ValueTask<ItemsProviderResult<GXDeviceTemplate>> GetItems(GXItemsProviderRequest request)
    {
        GXDeviceTemplate? filter = null;
        if (!string.IsNullOrEmpty(request.Filter))
        {
            //Search device templates by name
            filter = new GXDeviceTemplate() { Name = request.Filter };
        }
        ListDeviceTemplates req = new ListDeviceTemplates()
            {
                Index = request.StartIndex,
                Count = request.Count,
                Filter = filter,
                OrderBy = request.OrderBy,
                Descending = request.Descending,
                AllUsers = request.ShowAllUserData
            };
        var ret = await Http.PostAsJson<ListDeviceTemplatesResponse>("api/DeviceTemplate/List", req, request.CancellationToken);
        List<GXDeviceTemplate> list = new();
        //Add empty device template.
        list.Add(new GXDeviceTemplate() { Name = Properties.Resources.Nothing });
        if (ret.Templates != null)
        {
            list.AddRange(ret.Templates);
        }
        if (Settings?.DefaultDeviceTemplate != null)
        {
            foreach (var it in list)
            {
                if (it.Id == Settings?.DefaultDeviceTemplate)
                {
                    _defaultDeviceTemplate = it;
                    StateHasChanged();
                    break;
                }
            }
        }
        else
        {
            _defaultDeviceTemplate = list[0];
        }

        return new ItemsProviderResult<GXDeviceTemplate>(list, ret.Count);
    }
}
